// 函数介绍
// 函数是一段可以反复调用的代码块。函数还能接受输入的参数，不同的参数会返回不同的值。


// 函数的定义
// 函数的定义包括两个部分：函数名和函数体。函数体是一段可执行的代码，这段代码是用来实现特定功能的。
//
// 函数名是这个函数的标识符，函数名后的一对圆括号是函数体入口。函数体可以包含若干语句，甚至可以没有任何语句。
//
// 函数体内部的语句在执行时，一旦执行到return时，函数就执行完毕，并将结果返回。如果没有return语句，函数执行完毕后也会返回结果，只是结果为undefined。
//
// 函数执行完毕之后并不马上释放内存，而是等待垃圾回收机制调用，释放内存。也就是说，函数执行完毕并不会立即释放内存，而是等待垃圾回收机制调用，释放内存。

// 函数声明
function test() {
    console.log("Hello World!");
}


// 函数表达式
let test1 = function () {
    console.log("Hello World!");
}

// 箭头函数
const test2 = () => {
    console.log("Hello World!");
}

const test3 = () => console.log("Hello World!");
// 箭头函数没有自己的this，它的this是继承外面的，因此箭头函数中this指向的是它外层第一个不是箭头函数的函数的this。
// 箭头函数只有一行代码时，可以省略大括号。

test()



// todo 函数的参数

// 函数的参数
// 函数的参数在函数定义时并不需要指定类型，可以在函数调用时再指定类型。
//
// 函数的参数可以有默认值，也支持使用扩展运算符...来获取函数调用的参数。
//
// 函数的参数是按值传递的，传递方式是传值传递。也就是说，把函数外部的值复制给函数内部的参数，就和把值从一个变量复制到另一个变量一样。
//
// 但是当参数是复合类型的值（比如对象或者数组）时，传的是内存地址，因此在函数内部修改参数，将会影响到外部变量。
// 传入的参数多于定义的参数时，多出的参数被忽略。
// 传入的参数少于定义的参数时，没有传入的参数的值为undefined。




function test4(a,b=200) {
    console.log("Hello World!");
    c = a + b
    console.log(c)
}




test4(1,2)

test4(1)



let a = 500

function test5(b) {
    let a = 100
    b = 200
   let c = 300
    console.log(a, b, c)
}
test5()

console.log(a)
console.log(b)

// todo 函数调用栈
// 函数调用栈是用来管理函数调用关系的一种数据结构。当一个函数调用另一个函数时，会将其上下文信息（变量、函数等）压入调用栈，
// 等被调用函数执行完成后再将其上下文信息弹出，继续执行当前函数。
//
// 当发生函数调用时，会创建一个执行上下文，并且压入调用栈。等函数执行完成，将函数的执行上下文从栈中弹出。

























































































































